// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

package fuzz

// byteSliceRemoveBytes从b中删除一个随机字节块。
func byteSliceRemoveBytes(m *mutator, b []byte) []byte {
	if len(b) <= 1 {
		return nil
	}
	pos0 := m.rand(len(b))
	pos1 := pos0 + m.chooseLen(len(b)-pos0)
	copy(b[pos0:], b[pos1:])
	b = b[:len(b)-(pos1-pos0)]
	return b
}

// byteSliceInsertRandomBytes在随机
// 位置向b中插入一个随机字节块。
func byteSliceInsertRandomBytes(m *mutator, b []byte) []byte {
	pos := m.rand(len(b) + 1)
	n := m.chooseLen(1024)
	if len(b)+n >= cap(b) {
		return nil
	}
	b = b[:len(b)+n]
	copy(b[pos+n:], b[pos:])
	for i := 0; i < n; i++ {
		b[pos+i] = byte(m.rand(256))
	}
	return b
}

// byteSliceDuplicateBytes复制b中的一个字节块，并将其插入
// /随机位置。
func byteSliceDuplicateBytes(m *mutator, b []byte) []byte {
	if len(b) <= 1 {
		return nil
	}
	src := m.rand(len(b))
	dst := m.rand(len(b))
	for dst == src {
		dst = m.rand(len(b))
	}
	n := m.chooseLen(len(b) - src)
	// 使用片的结尾作为暂存空间，以避免执行
	// 分配。如果切片太小，请中止并尝试其他操作。
	if len(b)+(n*2) >= cap(b) {
		return nil
	}
	end := len(b)
	// 增加b的大小以适应复制的块以及
	// 一些额外的工作空间
	b = b[:end+(n*2)]
	// 将我们要复制的字节块复制到
	// 切片
	copy(b[end+n:], b[src:src+n])
	// 将拼接点n位置后的字节移到右侧
	// 为新块
	copy(b[dst+n:end+n], b[dst:end])
	// 将复制块插入拼接点
	copy(b[dst:], b[end+n:])
	b = b[:end+n]
	return b
}

// byteSliceOverwriteBytes用另一块b覆盖一块b。
func byteSliceOverwriteBytes(m *mutator, b []byte) []byte {
	if len(b) <= 1 {
		return nil
	}
	src := m.rand(len(b))
	dst := m.rand(len(b))
	for dst == src {
		dst = m.rand(len(b))
	}
	n := m.chooseLen(len(b) - src - 1)
	copy(b[dst:], b[src:src+n])
	return b
}

// byteSliceBitFlip翻转b中随机字节中的随机位。
func byteSliceBitFlip(m *mutator, b []byte) []byte {
	if len(b) == 0 {
		return nil
	}
	pos := m.rand(len(b))
	b[pos] ^= 1 << uint(m.rand(8))
	return b
}

// byteSliceXORByte用随机值异或b中的随机字节。
func byteSliceXORByte(m *mutator, b []byte) []byte {
	if len(b) == 0 {
		return nil
	}
	pos := m.rand(len(b))
	// 为了避免出现不可操作的情况（其中随机值与现有值匹配），请使用XOR，而不仅仅是将随机值设置为
	// 即可。
	b[pos] ^= byte(1 + m.rand(255))
	return b
}

// byteSliceSwapByte在b中交换两个随机字节。
func byteSliceSwapByte(m *mutator, b []byte) []byte {
	if len(b) <= 1 {
		return nil
	}
	src := m.rand(len(b))
	dst := m.rand(len(b))
	for dst == src {
		dst = m.rand(len(b))
	}
	b[src], b[dst] = b[dst], b[src]
	return b
}

// byteslicearithmaticunt8在b中添加/减去一个随机字节。
func byteSliceArithmeticUint8(m *mutator, b []byte) []byte {
	if len(b) == 0 {
		return nil
	}
	pos := m.rand(len(b))
	v := byte(m.rand(35) + 1)
	if m.r.bool() {
		b[pos] += v
	} else {
		b[pos] -= v
	}
	return b
}

// byteslicearithmaticunt16在b中添加/减去一个随机单元。
func byteSliceArithmeticUint16(m *mutator, b []byte) []byte {
	if len(b) < 2 {
		return nil
	}
	v := uint16(m.rand(35) + 1)
	if m.r.bool() {
		v = 0 - v
	}
	pos := m.rand(len(b) - 1)
	enc := m.randByteOrder()
	enc.PutUint16(b[pos:], enc.Uint16(b[pos:])+v)
	return b
}

// byteslicearithmaticunt32在b中添加/减去一个随机单元。
func byteSliceArithmeticUint32(m *mutator, b []byte) []byte {
	if len(b) < 4 {
		return nil
	}
	v := uint32(m.rand(35) + 1)
	if m.r.bool() {
		v = 0 - v
	}
	pos := m.rand(len(b) - 3)
	enc := m.randByteOrder()
	enc.PutUint32(b[pos:], enc.Uint32(b[pos:])+v)
	return b
}

func byteSliceArithmeticUint64(m *mutator, b []byte) []byte {
	if len(b) < 8 {
		return nil
	}
	v := uint64(m.rand(35) + 1)
	if m.r.bool() {
		v = 0 - v
	}
	pos := m.rand(len(b) - 7)
	enc := m.randByteOrder()
	enc.PutUint64(b[pos:], enc.Uint64(b[pos:])+v)
	return b
}

// ByteSliceOverwriteInteresting8用一个有趣的
// 值覆盖b中的随机字节。
func byteSliceOverwriteInterestingUint8(m *mutator, b []byte) []byte {
	if len(b) == 0 {
		return nil
	}
	pos := m.rand(len(b))
	b[pos] = byte(interesting8[m.rand(len(interesting8))])
	return b
}

// ByteSliceOverwriteInteresting16用一个有趣的
// 值覆盖b中的随机单元16。
func byteSliceOverwriteInterestingUint16(m *mutator, b []byte) []byte {
	if len(b) < 2 {
		return nil
	}
	pos := m.rand(len(b) - 1)
	v := uint16(interesting16[m.rand(len(interesting16))])
	m.randByteOrder().PutUint16(b[pos:], v)
	return b
}

// ByteSliceOverwriteInterestingInt32用一个有趣的
// 值覆盖b中的随机单元16。
func byteSliceOverwriteInterestingUint32(m *mutator, b []byte) []byte {
	if len(b) < 4 {
		return nil
	}
	pos := m.rand(len(b) - 3)
	v := uint32(interesting32[m.rand(len(interesting32))])
	m.randByteOrder().PutUint32(b[pos:], v)
	return b
}

// byteSliceInsertConstantBytes在b中的一个随机位置插入一个常量字节块。
func byteSliceInsertConstantBytes(m *mutator, b []byte) []byte {
	if len(b) <= 1 {
		return nil
	}
	dst := m.rand(len(b))
	// TODO（rolandshoemaker，katiehockman）：4096主要是随机挑选的
	// 。我们可能想要选择一个更大的值
	// （AFL使用32768，与类似的impl to chooseLen 
	// ，它偏向于随时间增长的较小长度），
	// 或根据语料库的特征设置最大值
	// （libFuzzer根据语料库中
	// 条目的最小/最大大小设置最小/最大值，然后从
	// 该范围内统一选取）。
	n := m.chooseLen(4096)
	if len(b)+n >= cap(b) {
		return nil
	}
	b = b[:len(b)+n]
	copy(b[dst+n:], b[dst:])
	rb := byte(m.rand(256))
	for i := dst; i < dst+n; i++ {
		b[i] = rb
	}
	return b
}

// byteSliceOverwriteConstantBytes用常量字节覆盖b块。
func byteSliceOverwriteConstantBytes(m *mutator, b []byte) []byte {
	if len(b) <= 1 {
		return nil
	}
	dst := m.rand(len(b))
	n := m.chooseLen(len(b) - dst)
	rb := byte(m.rand(256))
	for i := dst; i < dst+n; i++ {
		b[i] = rb
	}
	return b
}

// byteSliceShuffleBytes在b中洗牌一块字节。
func byteSliceShuffleBytes(m *mutator, b []byte) []byte {
	if len(b) <= 1 {
		return nil
	}
	dst := m.rand(len(b))
	n := m.chooseLen(len(b) - dst)
	if n <= 2 {
		return nil
	}
	// 从范围的末尾开始，向后迭代
	// 到dst，用
	// dst:dst+n（Fisher-Yates shuffle）中的另一个元素交换每个元素。
	for i := n - 1; i > 0; i-- {
		j := m.rand(i + 1)
		b[dst+i], b[dst+j] = b[dst+j], b[dst+i]
	}
	return b
}

// 字节交换b中的两个字节块。
func byteSliceSwapBytes(m *mutator, b []byte) []byte {
	if len(b) <= 1 {
		return nil
	}
	src := m.rand(len(b))
	dst := m.rand(len(b))
	for dst == src {
		dst = m.rand(len(b))
	}
	// 选择随机长度为len（b）-max（src，dst）
	// 这样我们就不会试图交换一个扩展到片尾
	// 之外的块
	max := dst
	if src > max {
		max = src
	}
	n := m.chooseLen(len(b) - max - 1)
	// 检查两个块是否相交，这样我们就不会复制部分输入，而不是交换它们。使用片的结尾作为暂存空间，以避免进行分配。如果切片太小，中止并尝试
	if src > dst && dst+n >= src || dst > src && src+n >= dst {
		return nil
	}
	// 其他方法。
	if len(b)+n >= cap(b) {
		return nil
	}
	end := len(b)
	b = b[:end+n]
	copy(b[end:], b[dst:dst+n])
	copy(b[dst:], b[src:src+n])
	copy(b[src:], b[end:])
	b = b[:end]
	return b
}
